﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Weazel.Willows.Model
{
	public partial class SignalFlowGraph 
		: HierarchicalEntity
	{
		private List<Weazel.Gezel.Model.Expression> expressions;
		public List<Weazel.Gezel.Model.Expression> Expressions
		{
			get { return expressions; }
		}

		public SignalFlowGraph(Module parent, string name) 
			: base(parent, name)
		{
			System.Diagnostics.Trace.Assert(parent != null);
			this.expressions = new List<Weazel.Gezel.Model.Expression>();
		}

		protected SignalFlowGraph()
			: base(null, null)
		{
			this.expressions = new List<Weazel.Gezel.Model.Expression>();
		}

		/// <summary>
		/// This method returns a list of identifiers being assigned
		/// by expressions in this sfg;
		/// </summary>		
		/// <returns>List of assigned identifers</returns>
		public List<string> GetAssignedIdentifiers()
		{
			List<string> result = new List<string>();

			// check each expression
			for (int j = 0; j < Expressions.Count; j++)
			{
				Weazel.Gezel.Model.Expression expression =
					Expressions[j];

				// assignments are always placed at the top level.
				// so no need to recusivily check children ..
				if (expression.ExpressionType ==
					Weazel.Gezel.Model.ExpressionType.Assignment)
				{
					Weazel.Gezel.Model.BinaryExpression assignmentExpression =
						expression as Weazel.Gezel.Model.BinaryExpression;

					Weazel.Gezel.Model.LeafExpression leaf =
						assignmentExpression.LeftChild as Weazel.Gezel.Model.LeafExpression;

					System.Diagnostics.Debug.Assert(leaf != null);

					// add to result set
					result.Add(leaf.value);
				}
			}

			return result;
		}

		/// <summary>
		/// This method returns a list of identifiers being read by
		/// expression in this sfg.
		/// </summary>
		/// <returns>List of read identifers</returns>
		public List<string> GetReadIdentifiers()
		{
			List<string> result = new List<string>();

			// check each expression
			for (int j = 0; j < Expressions.Count; j++)
			{
				Weazel.Gezel.Model.Expression expression =
					Expressions[j];

				Weazel.Gezel.Model.ExpressionDelegate dlg =
					new Weazel.Gezel.Model.ExpressionDelegate(checkExpressionForReadIdentifier);

				expression.RecursivilyInvokeDelegate(dlg, null, result);
			}

			return result;
		}

		/// <summary>
		/// Method used as an ExpressionDelegate to retrieve written identifiers
		/// from an expression tree.
		/// </summary>
		/// <param name="expression">current expression</param>
		/// <param name="parent">parent of current expression</param>
		/// <param name="parameters">List of read identifiers</param>
		private void checkExpressionForReadIdentifier(
			Weazel.Gezel.Model.Expression expression,
			Weazel.Gezel.Model.Expression parent,
			object parameters
		)
		{
			if (parent == null) // top level expression is NOT a write ..
				return;

			// cast user parameter
			List<string> result = parameters as List<string>;

			if (expression.ExpressionType == Weazel.Gezel.Model.ExpressionType.Identifier)
			{
				// must be a leaf expression
				Weazel.Gezel.Model.LeafExpression leaf =
					expression as Weazel.Gezel.Model.LeafExpression;

				// add to result if this is not the left hand side of an assignment
				bool addToResults = true;
				if (parent.ExpressionType == Weazel.Gezel.Model.ExpressionType.Assignment)
				{
					Weazel.Gezel.Model.BinaryExpression bin =
						parent as Weazel.Gezel.Model.BinaryExpression;

					if (bin.LeftChild == expression)
						addToResults = false;
				}

				if (addToResults)
					result.Add(leaf.value);
			}
		}
	}
}
